#include "StdAfx.h"
#include "ScannerImpl.h"
#include "STL_Buffer.h"
#include "AutomatVar1.h"
#include <assert.h>
#include <istream>
#include <fstream>
#include <iostream>
#include "SymtableV0.h"
#include "Test.h"


ScannerImpl::ScannerImpl(const char * const srcFile /*= NULL*/) :
    automat(NULL),//see below
    buffer(new STL_Buffer(srcFile)),
    symtable(new SymtableV0()),
    lexemFrac(new StringTabV0()),
    isTokenFound(false),
    isStop(false),
    token(NULL)
{
    automat = new AutomatVar1(this);
}

ScannerImpl::~ScannerImpl(void)
{
    delete automat;
    delete buffer;
    delete symtable;
    delete lexemFrac;
    delete token;//CLGR maybe the caller deletes all tokens (including this token)
}

Token* ScannerImpl::nextToken()
{
    if(isStop)
        return NULL;//case: a further call nextToken() returned the last token and stopped

    isTokenFound = false;
    isStop = false;
    token = NULL;
    int c = 0;
    char debug_char = 0;
    
    while(!isTokenFound && !isStop)
    {
        //trigger automat
        c = buffer->getchar();//if c == EOF symtable and automat handles it correctly
        debug_char = c;
        if(c != ' ') symtable->putChar(c);
        automat->readChar(c);
    }

    return token;//returns null, if isStop (in e.g. EOF case)
}

void ScannerImpl::freeToken(Token token)
{}

void ScannerImpl::mkToken(TType type, long long value)
{
    TokenData tData;
    if(type == TOK_IDENT) {
        tData.asKey = symtable->mkToken(type);
        token = new Token(type, 0, 0, tData);//CLGR TODO param 2 and 3 (line and column)
    } else if(type == TOK_INT) {
        tData.asInt = symtable->unputCharsAndGetAsInt();
        token = new Token(type, 0, 0, tData);//CLGR TODO param 2 and 3 (line and column)
    } else if(type == TOK_SIGN) {
        tData.asChar = (char) value;
        //symtable->unputAndGetChar();
        token = new Token(type, 0, 0, tData);//CLGR TODO param 2 and 3 (line and column)
    } else{
        //UNKNOWN TYPE!
        assert(false);
    }
    isTokenFound = true;
}

void ScannerImpl::ungetChar(int times/* = 1*/)
{
    buffer->ungetchar(times);
}

Information ScannerImpl::lookup(Key key)
{
    return symtable->lookup(key);
}

void ScannerImpl::stop()
{
    isStop = true;
}

int main()
{
    //Test::test();

    ScannerV0* scanner = new ScannerImpl("Test_Sign.txt");
    Token* t = NULL;
    while((t = scanner->nextToken()) != NULL)
    {
        switch(t->getType())
        {
            case TOK_IDENT:
                std::cout << "Identifier found: " << scanner->lookup(t->getKey()).lexem << std::endl;
                    break;
            case TOK_INT:
                    std::cout << "Integer    found: " << t->getInt() << std::endl;
                    break;
            case TOK_SIGN:
                    std::cout << "Sign       found: " << t->getChar() << std::endl;
                    break;
            default: //UNDEF
                break;
        }
    }
        
    return 0;
}